using System;
using JetBrains.Annotations;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Update;

namespace Microsoft.EntityFrameworkCore.Dm.Update.Internal;

public class DmModificationCommandBatch : AffectedCountModificationCommandBatch
{
	private const int DefaultNetworkPacketSizeBytes = 4096;

	private const int MaxScriptLength = 134217728;

	private const int MaxParameterCount = 2100;

	private const int MaxRowCount = 1000;

	private int _parameterCount = 1;

	private readonly int _maxBatchSize;

	private int _commandsLeftToLengthCheck = 50;

	protected virtual IDmUpdateSqlGenerator UpdateSqlGenerator => this.UpdateSqlGenerator;

	public DmModificationCommandBatch([NotNull] ModificationCommandBatchFactoryDependencies dependencies, int? maxBatchSize)
		: base(dependencies, (int?)null)
	{
		if (maxBatchSize.HasValue && maxBatchSize.Value <= 0)
		{
			throw new ArgumentOutOfRangeException("maxBatchSize", RelationalStrings.InvalidMaxBatchSize((object)maxBatchSize.Value));
		}
		_maxBatchSize = Math.Min(maxBatchSize.GetValueOrDefault(int.MaxValue), 1000);
	}

	protected bool CanAddCommand(IReadOnlyModificationCommand modificationCommand)
	{
		if (((ModificationCommandBatch)this).ModificationCommands.Count >= _maxBatchSize)
		{
			return false;
		}
		int num = CountParameters(modificationCommand);
		if (_parameterCount + num >= 2100)
		{
			return false;
		}
		_parameterCount += num;
		return true;
	}

	protected override bool IsValid()
	{
		if (--_commandsLeftToLengthCheck < 0)
		{
			int length = GetCommandText().Length;
			if (length >= 134217728)
			{
				return false;
			}
			int num = length / ((ModificationCommandBatch)this).ModificationCommands.Count;
			int num2 = (134217728 - length) / num;
			_commandsLeftToLengthCheck = Math.Max(1, num2 / 4);
		}
		return true;
	}

	protected int GetParameterCount()
	{
		return _parameterCount;
	}

	private static int CountParameters(IReadOnlyModificationCommand modificationCommand)
	{
		int num = 0;
		for (int i = 0; i < modificationCommand.ColumnModifications.Count; i++)
		{
			IColumnModification obj = modificationCommand.ColumnModifications[i];
			if (obj.UseCurrentValueParameter)
			{
				num++;
			}
			if (obj.UseOriginalValueParameter)
			{
				num++;
			}
		}
		return num;
	}

	protected string GetCommandText()
	{
		if (((ModificationCommandBatch)this).ModificationCommands.Count > 1)
		{
			return "BEGIN " + this.SqlBuilder.ToString() + " END; ";
		}
		return this.SqlBuilder.ToString();
	}
}
